﻿using CacheManager.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CacheManager.Serialization.Json;

namespace Shake.Framework.Services
{
    public class ShakeCacheManager<T> : IShakeCacheManager<T>
    {
        private ICacheManager<T> _manager;

        public ShakeCacheManager()
        {
            var cache = CacheFactory.Build<T>("ShakeCache", cnf =>
            {
                cnf.WithSystemRuntimeCacheHandle("RuntimeCacheHandler")
                    .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(60))
                .And
                .WithRedisConfiguration("ShakeRedisCache", redisCnf =>
                {
                    redisCnf.WithDatabase(0)
                        //.WithAllowAdmin()
                        .WithEndpoint("127.0.0.1", 6379);
                })
                .WithJsonSerializer()
                    //.WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(60))
                .WithMaxRetries(1000)
                .WithRetryTimeout(100)
                    //.WithRedisBackplane("ShakeRedis")
                .WithRedisCacheHandle("ShakeRedisCache", true);
            });
            _manager = cache;
        }

        public T AddOrUpdate(CacheItem<T> addItem, Func<T, T> updateValue, int maxRetries)
        {
            return _manager.AddOrUpdate(addItem, updateValue, maxRetries);
        }

        public T AddOrUpdate(CacheItem<T> addItem, Func<T, T> updateValue)
        {
            return _manager.AddOrUpdate(addItem, updateValue);
        }

        public T AddOrUpdate(string key, string region, T addValue, Func<T, T> updateValue, int maxRetries)
        {
            return _manager.AddOrUpdate(key, region, addValue, updateValue, maxRetries);
        }

        public T AddOrUpdate(string key, T addValue, Func<T, T> updateValue, int maxRetries)
        {
            return _manager.AddOrUpdate(key, addValue, updateValue, maxRetries);
        }

        public T AddOrUpdate(string key, string region, T addValue, Func<T, T> updateValue)
        {
            return _manager.AddOrUpdate(key, region, addValue, updateValue);
        }

        public T AddOrUpdate(string key, T addValue, Func<T, T> updateValue)
        {
            return _manager.AddOrUpdate(key, addValue, updateValue);
        }

        public IEnumerable<CacheManager.Core.Internal.BaseCacheHandle<T>> CacheHandles
        {
            get { return _manager.CacheHandles; }
        }

        public IReadOnlyCacheManagerConfiguration Configuration
        {
            get { return _manager.Configuration; }
        }

        public T GetOrAdd(string key, string region, Func<string, string, T> valueFactory)
        {
            return _manager.GetOrAdd(key, region, valueFactory);
        }

        public T GetOrAdd(string key, Func<string, T> valueFactory)
        {
            return _manager.GetOrAdd(key, valueFactory);
        }

        public T GetOrAdd(string key, string region, T value)
        {
            return _manager.GetOrAdd(key, region, value);
        }

        public T GetOrAdd(string key, T value)
        {
            return _manager.GetOrAdd(key, value);
        }

        public string Name
        {
            get { return _manager.Name; }
        }

        public event EventHandler<CacheManager.Core.Internal.CacheActionEventArgs> OnAdd;

        public event EventHandler<CacheManager.Core.Internal.CacheClearEventArgs> OnClear;

        public event EventHandler<CacheManager.Core.Internal.CacheClearRegionEventArgs> OnClearRegion;

        public event EventHandler<CacheManager.Core.Internal.CacheActionEventArgs> OnGet;

        public event EventHandler<CacheManager.Core.Internal.CacheActionEventArgs> OnPut;

        public event EventHandler<CacheManager.Core.Internal.CacheActionEventArgs> OnRemove;

        public event EventHandler<CacheManager.Core.Internal.CacheActionEventArgs> OnUpdate;

        public bool TryGetOrAdd(string key, string region, Func<string, string, T> valueFactory, out T value)
        {
            return _manager.TryGetOrAdd(key, region, valueFactory, out value);
        }

        public bool TryGetOrAdd(string key, Func<string, T> valueFactory, out T value)
        {
            return _manager.TryGetOrAdd(key, valueFactory, out value);
        }

        public bool TryUpdate(string key, string region, Func<T, T> updateValue, int maxRetries, out T value)
        {
            return _manager.TryUpdate(key, region, updateValue, maxRetries, out value);
        }

        public bool TryUpdate(string key, Func<T, T> updateValue, int maxRetries, out T value)
        {
            return _manager.TryUpdate(key, updateValue, maxRetries, out value);
        }

        public bool TryUpdate(string key, string region, Func<T, T> updateValue, out T value)
        {
            return _manager.TryUpdate(key, region, updateValue, out value);
        }

        public bool TryUpdate(string key, Func<T, T> updateValue, out T value)
        {
            return _manager.TryUpdate(key, updateValue, out value);
        }

        public T Update(string key, string region, Func<T, T> updateValue, int maxRetries)
        {
            return _manager.Update(key, region, updateValue, maxRetries);
        }

        public T Update(string key, Func<T, T> updateValue, int maxRetries)
        {
            return _manager.Update(key, updateValue, maxRetries);
        }

        public T Update(string key, string region, Func<T, T> updateValue)
        {
            return _manager.Update(key, region, updateValue);
        }

        public T Update(string key, Func<T, T> updateValue)
        {
            return _manager.Update(key, updateValue);
        }

        public bool Add(CacheItem<T> item)
        {
            return _manager.Add(item);
        }

        public bool Add(string key, T value, string region)
        {
            return _manager.Add(key, value, region);
        }

        public bool Add(string key, T value)
        {
            return _manager.Add(key, value);
        }

        public void Clear()
        {
            _manager.Clear();
        }

        public void ClearRegion(string region)
        {
            _manager.ClearRegion(region);
        }

        public bool Exists(string key, string region)
        {
            return _manager.Exists(key, region);
        }

        public bool Exists(string key)
        {
            return _manager.Exists(key);
        }

        public void Expire(string key, string region, TimeSpan slidingExpiration)
        {
            _manager.Expire(key, region, slidingExpiration);
        }

        public void Expire(string key, TimeSpan slidingExpiration)
        {
            _manager.Expire(key, slidingExpiration);
        }

        public void Expire(string key, string region, DateTimeOffset absoluteExpiration)
        {
            _manager.Expire(key, region, absoluteExpiration);
        }

        public void Expire(string key, DateTimeOffset absoluteExpiration)
        {
            _manager.Expire(key, absoluteExpiration);
        }

        public void Expire(string key, string region, ExpirationMode mode, TimeSpan timeout)
        {
            _manager.Expire(key, region, mode, timeout);
        }

        public void Expire(string key, ExpirationMode mode, TimeSpan timeout)
        {
            _manager.Expire(key, mode, timeout);
        }

        public TOut Get<TOut>(string key, string region)
        {
            return _manager.Get<TOut>(key, region);
        }

        public TOut Get<TOut>(string key)
        {
            return _manager.Get<TOut>(key);
        }

        public T Get(string key, string region)
        {
            return _manager.Get(key, region);
        }

        public T Get(string key)
        {
            return _manager.Get(key);
        }

        public CacheItem<T> GetCacheItem(string key, string region)
        {
            return _manager.GetCacheItem(key, region);
        }

        public CacheItem<T> GetCacheItem(string key)
        {
            return _manager.GetCacheItem(key);
        }

        public void Put(CacheItem<T> item)
        {
            _manager.Put(item);
        }

        public void Put(string key, T value, string region)
        {
            _manager.Put(key, value, region);
        }

        public void Put(string key, T value)
        {
            _manager.Put(key, value);
        }

        public bool Remove(string key, string region)
        {
            return _manager.Remove(key, region);
        }

        public bool Remove(string key)
        {
            return _manager.Remove(key);
        }

        public void RemoveExpiration(string key, string region)
        {
            _manager.RemoveExpiration(key, region);
        }

        public void RemoveExpiration(string key)
        {
            _manager.RemoveExpiration(key);
        }

        public T this[string key, string region]
        {
            get
            {
                return _manager[key, region];
            }
            set
            {
                _manager[key, region] = value;
            }
        }

        public T this[string key]
        {
            get
            {
                return _manager[key];
            }
            set
            {
                _manager[key] = value;
            }
        }

        public void Dispose()
        {
            _manager.Dispose();
        }
    }
}
